/**
 * 
 */
package edu.sjtu.se.prophet.io.gson;

import java.lang.reflect.Type;
import java.util.Map;

import org.apache.log4j.Logger;

import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

import edu.sjtu.se.prophet.exception.EdgeExistsException;
import edu.sjtu.se.prophet.exception.NodeExistsException;
import edu.sjtu.se.prophet.exception.NodeNotFoundException;
import edu.sjtu.se.prophet.graph.Edge;
import edu.sjtu.se.prophet.graph.Graph;
import edu.sjtu.se.prophet.graph.Node;

/**
 * @author willard
 * 
 */
public class GraphDeserializer implements JsonDeserializer<Graph> {
    private static Logger logger = Logger.getLogger(GraphDeserializer.class);

    @Override
    public Graph deserialize(JsonElement json, Type type,
            JsonDeserializationContext context) throws JsonParseException {
        Graph graph = new Graph();
        for (Map.Entry<String, JsonElement> entry : json.getAsJsonObject()
                .entrySet()) {
            if ("meta".equals(entry.getKey())) {
                for (Map.Entry<String, JsonElement> m : entry.getValue()
                        .getAsJsonObject().entrySet()) {
                    graph.getMeta().put(m.getKey(),
                            context.deserialize(m.getValue(), Object.class));
                }
            } else if ("nodes".equals(entry.getKey())) {
                JsonArray nodesArray = entry.getValue().getAsJsonArray();
                for (int i = 0; i < nodesArray.size(); i++) {
                    String nodeId = "";
                    try {
                        Node node = (Node) context.deserialize(
                                nodesArray.get(i), Node.class);
                        nodeId = node.getId();
                        graph.addNode(node);
                        logger.info("Added node: " + node);
                    } catch (NodeExistsException e) {
                        logger.error("Node " + nodeId, e);
                    }
                }
            } else if ("edges".equals(entry.getKey())) {
                JsonArray nodesArray = entry.getValue().getAsJsonArray();
                for (int i = 0; i < nodesArray.size(); i++) {
                    String fromId = "";
                    String endId = "";
                    try {
                        Edge temp = (Edge) context.deserialize(
                                nodesArray.get(i), Edge.class);
                        fromId = temp.getStart().getId();
                        endId = temp.getEnd()
                                .getId();
                        graph.addEdge(fromId, endId);
                    } catch (EdgeExistsException e) {
                        logger.error("Edge from " + fromId + " to " + endId, e);
                    } catch (NodeNotFoundException e) {
                        logger.error("Edge from " + fromId + " to " + endId, e);
                    }
                }
            }
        }
        return graph;
    }

}
